import java.util.HashMap;
import java.util.Map;

import javax.swing.JTextArea;

public class Bus extends Constants {
	public static Map<Integer, String> instructionMemory = new HashMap<Integer, String>();
	public static int Cycle = 0;
	// The bus has only ONE method which will connect ALL the components
	// together
	// no matter what the instruction is
	public static void startSequence(JTextArea out) {
		while (instructionMemory.containsKey(PC.currentAddress)) {
			System.out.println("\n-------------- Cycle " + Cycle++ +" ------------------");
			out.append("\n-------------- Cycle " + Cycle +" ------------------");
			Instruction.set(instructionMemory.get(PC.currentAddress));

			RegisterFile.readOperation(Instruction.RS_REGISTER,
					Instruction.RT_REGISTER);

			ALU.performOperation(RegisterFile.ReadData1,
					RegisterFile.ReadData2, Instruction.Immediate,
					ALUOperation, ALUSrc);

			Memory.memoryOperation(MemWrite, MemRead, MemtoReg, ALU.ALUResult,
					RegisterFile.ReadData2);

			RegisterFile.writeOperation(Memory.memOutput,
					Instruction.RD_REGISTER, Instruction.RT_REGISTER,
					Registers.$ra, RegDst, RegWrite, JAL);

			PC.PCAlteration(Branch, Branch2, Jump, ALU.Zero,
					Instruction.Immediate, Instruction.JUMP_ADDRESS);
			
			System.out.println("Instruction & Datapath: " + Instruction.Display() + "Register file: " + RegisterFile.registerValues + "\nMemory: " + Memory.memoryValues);
			out.append("Instruction & Datapath: " + Instruction.Display() + "Register file: " + RegisterFile.registerValues + "\nMemory: " + Memory.memoryValues);
		}
	}

	public static void setInitialValues(Map<Integer, String> instructionMemory,
			int codeStart) {
		PC.currentAddress = codeStart;
		Bus.instructionMemory = instructionMemory;
		Bus.Cycle = 0;
	}

	public static void main(String[] args) {
		instructionMemory.put(0, "Addi $t6, $t6, 5");
		instructionMemory.put(4, "Add $t1, $t2, $t1");
		instructionMemory.put(8, "Addi $t1, $t1, 200");
		instructionMemory.put(12, "addi $t2, $t1, 200");
		instructionMemory.put(16, "Add $t3, $t1, $t2");
		instructionMemory.put(20, "SLTi $t1, $t3, 120");
		instructionMemory.put(24, "addi $t5, $t5, 1");
		instructionMemory.put(28, "bne $t5, $t6, 24");
		instructionMemory.put(32, "JAL 64");
		setInitialValues(instructionMemory, 0);
		startSequence(new JTextArea());
	}

	public static int getValidJumpAddress(int from, int to) {
		/*
		    currentAddress &= 0xf0000000;
			jumpAddress = jumpAddress << 2;
			currentAddress = currentAddress | jumpAddress;

		 */
		
		to &= 0x0fffffff;
		to >>>= 2;
		return to;
	}

	public static int getValidBranchAddress(int from, int to){
		//from = 28;
		// to = 24;
		to -= from + 4;
		to /= 4;
		return to;
	}
}
